package com.ants.boot.utils.pdf;

import com.ants.boot.utils.pdf.exception.PdfExportException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.PDFTextStripper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 蚂蚁会花呗
 * @create 2025/3/5 17:25
 * pdf 转换成其他格式，比如图片，word
 */
public class PdfConvertUtils {
    private static Logger logger = LoggerFactory.getLogger(PdfConvertUtils.class);

    /**
     * 默认的图片像素
     */
    private static final float DEFAULT_DPI = 300f;

    /**
     * 默认图片后缀
     */
    private static final String DEFAULT_SUFFIX_PNG = "png";

    /**
     * 逗号
     */
    private static final String STRING_COMMA = ".";


    /**
     * 将二进制pdf文件转换成二进制图片
     * @param file  pdf文档的路径和名称
     * @return 返回二进制图片数组
     */
    public static List<byte[]> convertToImgMultipartFile(MultipartFile file){
        return convert(file,DEFAULT_SUFFIX_PNG, DEFAULT_DPI);
    }

    /**
     * 将二进制pdf文件转换成二进制图片
     * @param file  pdf文档的路径和名称
     * @param imgType 图片类型 png、jpg等
     * @return 返回二进制图片数组
     */
    public static List<byte[]> convertToImgMultipartFile(MultipartFile file,String imgType){
        return convertToImgMultipartFile(file,imgType,DEFAULT_DPI);
    }

    /**
     * 将二进制pdf文件转换成二进制图片
     * @param file  pdf文档的路径和名称
     * @param imgType 图片类型 png、jpg等
     * @param dpi 像素
     * @return 返回二进制图片数组
     */
    public static List<byte[]> convertToImgMultipartFile(MultipartFile file,String imgType,Float dpi){
        if (imgType == null){
            imgType = DEFAULT_SUFFIX_PNG;
        }
        return convert(file,imgType,dpi);
    }

    /**
     * pdf文档转图片,转换后的图片路径就是参数pdfPathAndName的路径
     * @param pdfPathAndName  pdf文档的路径和名称
     * @return 返回图片的名称,多页用逗号分割
     */
    public static String convertToImg(String pdfPathAndName){
        File file = new File(pdfPathAndName);
        return convertToImg(file.getParent(), file.getName());
    }

    /**
     * pdf文档转图片,转换后的图片路径就是参数pdfUrl的路径
     * @param pdfPath  pdf文档的路径
     * @param pdfName pdf文档的名称
     * @return 返回图片的名称多页用逗号分割
     */
    public static String convertToImg(String pdfPath, String pdfName){
        if (pdfPath == null || pdfName == null){
            throw new PdfExportException("图片路径或者名称不能为空");
        }
        //判断结尾是否有斜杠
        if (!pdfPath.endsWith("\\") || !pdfPath.endsWith("/")){
            pdfPath = pdfPath + "/";
        }
        return convertToImg(pdfPath, pdfName, pdfPath,DEFAULT_DPI);
    }

    /**
     * pdf文档转图片
     * @param pdfPath pdf 路径
     * @param pdfName pdf 名称
     * @param imgPath 转换后的图片路径
     * @return 图片的名称
     */
    public static String convertToImg(String pdfPath,String pdfName,String imgPath){
        return convert(pdfPath,pdfName,imgPath,DEFAULT_DPI);
    }

    /**
     * pdf文档转图片
     * @param pdfPath pdf 路径
     * @param pdfName pdf 名称
     * @param imgPath 转换后的图片路径
     * @param dpi 图片像素
     * @return 图片的名称
     */
    public static String convertToImg(String pdfPath,String pdfName,String imgPath,Float dpi){
        return convert(pdfPath,pdfName,imgPath,dpi);
    }

    private static String convert(String pdfPath,String pdfName,String imgPath,Float dpi){
        if (pdfPath == null){
            throw new PdfExportException("图片路径不能为空");
        }
        logger.info("开始转换成图片，图片路径是：" + pdfPath);
        try{
            List<String> listImages = new ArrayList<>();
            PDDocument document = PDDocument.load(new File(pdfPath + pdfName));
            PDFRenderer renderer = new PDFRenderer(document);
            for (int page = 0; page<document.getNumberOfPages();page++){
                // 将 PDF 页面渲染成图像
                BufferedImage image = renderer.renderImageWithDPI(page, dpi, ImageType.RGB);
                // 将图像保存成 PNG 文件
                File pngFile = File.createTempFile("images",STRING_COMMA + DEFAULT_SUFFIX_PNG,new File(imgPath));
                ImageIO.write(image, DEFAULT_SUFFIX_PNG, pngFile);
                listImages.add(pngFile.getName());
            }
            return String.join(",",listImages);
        } catch (IOException e) {
            e.printStackTrace();
            throw new PdfExportException("图片路径不能为空:" + e.getMessage());
        }
    }

    private static List<byte[]> convert(MultipartFile file,String imgType, Float dpi){
        logger.info("MultipartFile 开始转换成图片");
        try{
            PDDocument document = PDDocument.load(file.getBytes());
            PDFRenderer renderer = new PDFRenderer(document);
            // 将 PDF 页面渲染成图像
            List<byte[]> listImages = new ArrayList<>();
            for (int page = 0; page < document.getNumberOfPages(); page++) {
                BufferedImage image = renderer.renderImageWithDPI(page, dpi, ImageType.RGB);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ImageIO.write(image, imgType, outputStream);
                byte[] bytes = outputStream.toByteArray();
                listImages.add(bytes);
            }
            return  listImages;
        } catch (IOException e) {
            e.printStackTrace();
            throw new PdfExportException("pdf MultipartFile 转换图片失败:" + e.getMessage());
        }
    }

    /**
     * pdf 转world
     * @param pdfPath pdf 路径
     * @param pdfName pdf 名称
     * @return
     */
    public static byte[] convertToWord(String pdfPath,String pdfName){
        try{
            PDDocument document = PDDocument.load(new File(pdfPath + pdfName));
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            Writer writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
            PDFTextStripper stripper = new PDFTextStripper();
            stripper.setSortByPosition(true);
            stripper.setStartPage(0);
            stripper.setEndPage(document.getNumberOfPages());
            stripper.writeText(document, writer);
            writer.close();
            return outputStream.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
            throw new PdfExportException("pdf 转换成world失败" + e.getMessage());
        }
    }

    public static void main(String[] args) throws IOException {
//        System.out.println(convertToImg("D:/tmp/test/pdf/test.pdf"));
//        System.out.println(convertToImg("D:\\tmp\\test\\pdf\\test.pdf"));
//        System.out.println(convertToImg("D:\\tmp\\test\\pdf","test.pdf"));
//        System.out.println(convertToImg("D:/tmp/test/pdf","test.pdf"));
//        convertOneImg("D:\\tmp\\test\\pdf\\","test.pdf","D:\\tmp\\test\\pdf\\");
//        List<String> list = new ArrayList<>();
//        list.add("1111");
//        System.out.println(String.join(",",list));

    }

}
